package simco.framework.xml;

import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.TransformerException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import com.sun.org.apache.xpath.internal.XPathAPI;

public class XmlParser {
	
	/**
	 *  File instance of reading file.
	 */
	private File file;
	
	/**
	 * Defines a factory API
	 * that enables applications to obtain a parser that produces DOM object trees from XML documents. 
	 */
	private DocumentBuilderFactory dbf;
	
	/**
	 * Defines the API to obtain DOM Document instances from an XML document. 
	 */
	private DocumentBuilder db;
	
	/**
	 * The document interface represents the entire XML document. 
	 */
	private Document doc;
	
	/**
	 * The XPath expression to parsing xml file. 
	 */
	private XPathExpression xPathExpression = null;
	
	/**
	 * The XPath to parsing xml file.  
	 */
	private XPath xPath;
	
	/**
	 * True if xml file has been successfully read, false otherwise.
	 */
	private boolean state;
	
	/**
	 * Constructor of this class.
	 * 
	 * @param path - Path to the xml file.
	 */
	public XmlParser(String path)
	{
		super();
		
		this.state = true;
		try {
			this.file = new File(path);
			this.dbf = DocumentBuilderFactory.newInstance();
			this.db = dbf.newDocumentBuilder();
			this.doc = db.parse(file);
			xPath =  XPathFactory.newInstance().newXPath();
		} catch (Exception e) {
			this.state = false;
			//e.printStackTrace();
		}
	}
	
	/**
	 * Read Long value from xml file.
	 * 
	 * @param expression - XPath to the Long value.
	 * @param errorValue - It is used when Long values hasn't been found.
	 * @return Long value.
	 */
	public long readLong(String expression, long errorValue)
	{
		if(!state) return errorValue;
		long val;
		try {
			xPathExpression = xPath.compile(expression);
			val = Long.parseLong((String)xPathExpression.evaluate(doc, XPathConstants.STRING));
		} catch (Exception e) {
			val = errorValue;
			//e.printStackTrace();
		}
		return val;
	}
	
	/**
	 * Read Integer value from xml file.
	 * 
	 * @param expression - XPath to the Integer value.
	 * @param errorValue - It is used when Integer values hasn't been found.
	 * @return Integer value.
	 */
	public int readInt(String expression, int errorValue)
	{
		if(!state) return errorValue;
		int val;
		try {
			xPathExpression = xPath.compile(expression);
			val = Integer.parseInt((String)xPathExpression.evaluate(doc, XPathConstants.STRING));
		} catch (Exception e) {
			val = errorValue;
			//e.printStackTrace();
		}
		return val;
	}
	
	/**
	 * Read String value from xml file.
	 * 
	 * @param expression - XPath to the String value.
	 * @param errorValue - It is used when String values hasn't been found.
	 * @return String value.
	 */
	public String readString(String expression, String errorValue)
	{
		if(!state) return errorValue;
		String val;
		try {
			xPathExpression = xPath.compile(expression);
			val = (String)xPathExpression.evaluate(doc, XPathConstants.STRING);
		} catch (XPathExpressionException e) {
			val = errorValue;
			//e.printStackTrace();
		}
		return val;
	}
	
	/**
	 * Read Node list from xml file.
	 * 
	 * @param expression - XPath to the Node list.
	 * @return Node list.
	 */
	public NodeList selectNodeList(String expression)
	{
		if(!state){
			System.out.println("Tady je chyba"+" "+this.file.getPath());
			return null;
		}
		NodeList val;
		try {
			val = XPathAPI.selectNodeList(this.doc, expression);
		} catch (TransformerException e) {
			val = null;
			//e.printStackTrace();
		}
		return val;
	}
}
